﻿package systems.traer 
{
	public class Attraction implements Force
	{
		
		private var _p0:Particle;
		private var _p1:Particle;
		private var _strength:Number;
		private var _on:Boolean;
		private var _distanceMin:Number;
		private var distanceMinSquared:Number;
		
		
		/**
		 * 
		 * @param	p0
		 * @param	p1
		 * @param	strength
		 * @param	distanceMin
		 */
		public function Attraction( p0:Particle, p1:Particle, strength:Number, distanceMin:Number )
		{
			
			_p0 = p0;
			_p1 = p1;
			
			_on = true;
			_strength = strength;
			_distanceMin = distanceMin;
			
			distanceMinSquared = _distanceMin * _distanceMin;
			
		}
		
		public final function getMinimumDistance( d:Number ):Number
		{
			distanceMin = d;
			distanceMinSquared = d * d;
			return distanceMinSquared;
		}
		
		//public final function turnOff():void {
			//on = false;
		//}
		//public final function turnOn():void {
			//on = true;
		//}
		//
		
		//public final function setStrength(_k:Number):void {
			//k = _k;
		//}
		//public final function getOneEnd():Particle {
			//return a;
		//}
		//public final function getTheOtherEnd():Particle {
			//return p1;
		//}
		//public final function getStrength():Number {
			//return k;
		//}
		
		public function apply():void
		{
			if ( on && ( !p0.fixed || !p1.fixed ) )
			{
				
				var a2bX:Number = p0.position.x - p1.position.x;
				var a2bY:Number = p0.position.y - p1.position.y;
				var a2bZ:Number = p0.position.z - p1.position.z;

				var a2bDistanceSquared:Number = a2bX * a2bX + a2bY * a2bY + a2bZ * a2bZ;
				
				if ( a2bDistanceSquared < distanceMinSquared )
				{
					a2bDistanceSquared = distanceMinSquared;
				}

				var force:Number = strength * p0.mass * p1.mass / a2bDistanceSquared;

				var length:Number = Math.sqrt( a2bDistanceSquared );
				
				// make unit vector
				
				a2bX /= length;
				a2bY /= length;
				a2bZ /= length;
				
				// multiply by force 
				
				a2bX *= force;
				a2bY *= force;
				a2bZ *= force;

				// apply
				
				if ( !p0.fixed )
				{
					//p0.force.addFromValues( -a2bX, -a2bY, -a2bZ );
					p0.force.x += -a2bX;
					p0.force.y += -a2bY;
					p0.force.z += -a2bZ;
				}
				
				if ( !p1.fixed )
				{
					//p1.force.addFromValues( a2bX, a2bY, a2bZ );
					p1.force.x += a2bX;
					p1.force.y += a2bY;
					p1.force.z += a2bZ;
				}
			}
			
		}
		public function get on():Boolean { return _on; }
		
		public function set on(value:Boolean):void 
		{
			_on = value;
		}
		
		public function get p0():Particle { return _p0; }
		
		public function set p0(value:Particle):void 
		{
			_p0 = value;
		}
		
		public function get p1():Particle { return _p1; }
		
		public function set p1(value:Particle):void 
		{
			_p1 = value;
		}
		
		
		public function get strength():Number { return _strength; }
		
		public function set strength(value:Number):void 
		{
			_strength = value;
		}
		
		public function get distanceMin():Number { return _distanceMin; }
		
		public function set distanceMin(value:Number):void 
		{
			_distanceMin = value;
		}
		
	}

}